/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.xuexiang.xui_lib.component.banner;

import ohos.agp.animation.Animator;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.PageSlider;
import ohos.agp.components.StackLayout;
import ohos.agp.utils.Point;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.multimodalinput.event.TouchEvent;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.component.banner.anim.BaseAnimator;
import com.xuexiang.xui_lib.component.banner.interfaces.OnItemClickListener;
import com.xuexiang.xui_lib.component.banner.transform.PageTransformer;
import com.xuexiang.xui_lib.component.banner.widget.BannerItem;
import com.xuexiang.xui_lib.util.TypedAttrUtils;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static ohos.multimodalinput.event.TouchEvent.CANCEL;
import static ohos.multimodalinput.event.TouchEvent.NONE;
import static ohos.multimodalinput.event.TouchEvent.PRIMARY_POINT_DOWN;
import static ohos.multimodalinput.event.TouchEvent.PRIMARY_POINT_UP;

/**
 * 使用PageSlider实现Banner图
 *
 * @since 2021-04-28
 */
public class SimpleImageBanner extends StackLayout implements
    PageSlider.PageChangedListener, Component.TouchEventListener {
    private final int indicatorDefaultSelectRes = ResourceTable.Media_ic_banner_dot_select;
    private final int indicatorDefaultUnselectRes = ResourceTable.Media_ic_banner_dot_unselect;
    private int shapeIndicatorUnselectOval = ResourceTable.Graphic_shape_indicator_unselect_oval;
    private int shapeIndicatorSelectOval = ResourceTable.Graphic_shape_indicator_select_oval;
    private static final int constant = 1000;
    private static final int displayHeight = 200;
    private static final int deFaultTime = 5;
    private static final int deFaultIndicatorWidth = 6;
    private boolean isShowText;
    private boolean isIndicatorShow;
    private boolean isRadiusImage;
    private int indicatorWidth;
    private int indicatorHeight;
    private int indicatorSelectRes;
    private int indicatorUnselectRes;
    private int indicatorRadius;
    private float scale;
    private String barColor;
    private String indicatorStyle;
    private String indicatorGravity;
    private SwitchTask adSwitchTask;
    private StackLayout stackLayout;
    private BannerViewPager bannerViewPager;
    private CircleIndicator directionalLayout;
    private int count;
    private int currentItem;
    private long period; // 默认5秒
    private long delay; // 延时默认5秒
    private Class<? extends BaseAnimator> mSelectAnimClass;
//    private Class<? extends BaseAnimator> mUnselectAnimClass;
    private Class<? extends PageTransformer> transformer;
    private List<BannerItem> dataList;
    private OnItemClickListener onItemClickListener;
    private EventHandler handler = new EventHandler(EventRunner.current());

    /**
     * 构造参数
     *
     * @param context
     */
    public SimpleImageBanner(Context context) {
        super(context);
        init(null);
    }

    /**
     * 构造参数
     *
     * @param context
     * @param attrSet
     */
    public SimpleImageBanner(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init(attrSet);
        initView();
        initData();
    }

    private void init(AttrSet attrSet) {
        dataList = new ArrayList<>();
        if (attrSet != null) {
            indicatorWidth = TypedAttrUtils.getDimensionPixelSize(attrSet, "bb_indicatorWidth", 0); // 指示器圆球宽度
            indicatorHeight = TypedAttrUtils.getDimensionPixelSize(attrSet, "bb_indicatorHeight", 0); // 指示器圆球高度
            indicatorGravity = TypedAttrUtils.getString(attrSet, "bb_indicatorGravity", "CENTER"); // 指示器布局位置
            scale = TypedAttrUtils.getFloat(attrSet, "bb_scale", 0.0f); // 根据scale进行调整Banner图高度
            isRadiusImage = TypedAttrUtils.getBoolean(attrSet, "bb_radiusImage", false); // 是否显示圆角图片
            isIndicatorShow = TypedAttrUtils.getBoolean(attrSet, "bb_isIndicatorShow", true); // 是否显示文本图片轮播图
            indicatorStyle = TypedAttrUtils.getString(attrSet, "bb_indicatorStyle", "CORNER"); // 指示器圆球形状
            indicatorRadius = TypedAttrUtils.getDimensionPixelSize(attrSet, "bb_indicatorCornerRadius", 0); // 指示器形状角度
            String selectRes = TypedAttrUtils.getString(attrSet, "bb_indicatorSelectRes", ""); // 指示器制定选中图片
            if ("".equals(selectRes)) {
                indicatorSelectRes = indicatorDefaultSelectRes;
            } else {
                int index = selectRes.indexOf(":");
                selectRes = selectRes.substring(index + 1);
                indicatorSelectRes = Integer.parseInt(selectRes);
            }
            String unSelectRes = TypedAttrUtils.getString(attrSet, "bb_indicatorUnselectRes", ""); // 指示器制定未选中图片
            if ("".equals(unSelectRes)) {
                indicatorUnselectRes = indicatorDefaultUnselectRes;
            } else {
                int index = unSelectRes.indexOf(":");
                unSelectRes = unSelectRes.substring(index + 1);
                indicatorUnselectRes = Integer.parseInt(unSelectRes);
            }
            isShowText = TypedAttrUtils.getBoolean(attrSet, "bb_showText", false); // 指示器是否显示文本
            barColor = TypedAttrUtils.getString(attrSet, "bb_barColor", "#00000000"); // 是否设置底部背景颜色
            period = TypedAttrUtils.getDimensionPixelSize(attrSet, "bb_period", deFaultTime); // 获取轮播图时间间隔
            period = period * constant;
            delay = TypedAttrUtils.getDimensionPixelSize(attrSet, "bb_delay", deFaultTime); // 延迟多少秒进行
            delay = delay * constant;
        }
    }

    private void initView() {
        LayoutScatter instance = LayoutScatter.getInstance(getContext());
        Component component = instance.parse(ResourceTable.Layout_include_viewpager, this, true);
        stackLayout = (StackLayout) component.findComponentById(ResourceTable.Id_bannerContainer);
        bannerViewPager = (BannerViewPager) component.findComponentById(ResourceTable.Id_bannerViewPager);
        directionalLayout = (CircleIndicator) component.findComponentById(ResourceTable.Id_circleIndicator2);
        DisplayManager displayManager = DisplayManager.getInstance();
        Optional<Display> defaultDisplay = displayManager.getDefaultDisplay(getContext()); // 根据scale 计算Banner高度
        Point point = new Point();
        defaultDisplay.get().getSize(point);
        int width = defaultDisplay.get().getAttributes().width; // 获取屏幕宽度
        ComponentContainer.LayoutConfig layoutConfig = stackLayout.getLayoutConfig();
        if (isIndicatorShow) {
            if (scale <= 0) {
                layoutConfig.height = AttrHelper.vp2px(displayHeight, getContext());
            } else {
                layoutConfig.height = (int) (width * scale);
            }
        }
        stackLayout.setLayoutConfig(layoutConfig);
        directionalLayout.setVisibility(isIndicatorShow ? VISIBLE : HIDE);
    }

    private void initData() {
        if (indicatorWidth == 0 || indicatorHeight == 0) {
            indicatorWidth = AttrHelper.vp2px(deFaultIndicatorWidth, getContext());
            indicatorHeight = AttrHelper.vp2px(deFaultIndicatorWidth, getContext());
        } else { // 转换单位
            indicatorWidth = AttrHelper.vp2px(indicatorWidth, getContext());
            indicatorHeight = AttrHelper.vp2px(indicatorHeight, getContext());
        }
    }

    /**
     * 配置数据
     *
     * @return 当前SimpleImageBanner
     */
    public SimpleImageBanner configData() {
        setConfigData();
        return this;
    }

    private void setConfigData() {
        count = dataList.get(0).getImgUrl().size();
        bannerViewPager.setIndicatorShow(isIndicatorShow);
        bannerViewPager.setRadiusImage(isRadiusImage);
        bannerViewPager.setTransformer(transformer);
        bannerViewPager.setOnItemClickListener(onItemClickListener);
        bannerViewPager.setData(dataList.get(0));
        bannerViewPager.setPageChangedListener(this);
        directionalLayout.setIndicatorWidth(indicatorWidth);
        directionalLayout.setIndicatorHeight(indicatorHeight);
        directionalLayout.setIndicatorGravity(indicatorGravity);
        directionalLayout.setIndicatorStyle(indicatorStyle);
        directionalLayout.setIndicatorCornerRadius(indicatorRadius);
        directionalLayout.setShapeIndicatorSelectOval(shapeIndicatorSelectOval);
        directionalLayout.setShapeIndicatorUnselectOval(shapeIndicatorUnselectOval);
        directionalLayout.setIndicatorDefaultSelectRes(indicatorSelectRes);
        directionalLayout.setIndicatorDefaultUnselectRes(indicatorUnselectRes);
        directionalLayout.setShowText(isShowText);
        directionalLayout.setBarColor(barColor);
        directionalLayout.setViewData(dataList.get(0).getTitle());
        directionalLayout.setSelectAnimClass(mSelectAnimClass);
        directionalLayout.setFirstIndicator();
        adSwitchTask = new SwitchTask(this);
        setTouchEventListener(this);
    }

    /**
     * 开始滚动
     */
    public void startScroll() {
        handler.postTask(adSwitchTask, delay);
    }

    /**
     * 停止滚动
     */
    public void stopTurning() {
        handler.removeTask(adSwitchTask);
    }

    @Override
    public void onPageSliding(int itemPos, float itemPosOffset, int itemPosOffsetPixels) {
        // nothing
    }

    @Override
    public void onPageSlideStateChanged(int i) {
        // nothing
    }

    @Override
    public void onPageChosen(int position) {
        int index = position % count;
        directionalLayout.setIndicator(index); // 指示器跟着ViewPager滑动
        directionalLayout.setTextShow(index);
    }

    /**
     * 设置侧滑缩小动画
     *
     * @param transformer
     * @return 返回当前SimpleImageBanner
     */
    public SimpleImageBanner setTransformer(Class<? extends PageTransformer> transformer) {
        this.transformer = transformer;
        return this;
    }

    /**
     * 设置显示器选中动画
     *
     * @param selectAnimClass
     * @return 返回当前SimpleImageBanner
     */
    public SimpleImageBanner setSelectAnimClass(Class<? extends BaseAnimator> selectAnimClass) {
        this.mSelectAnimClass = selectAnimClass;
        return this;
    }

    /**
     * 设置显示器未选中动画
     *
     * @param unselectAnimClass
     * @return 返回当前SimpleImageBanner
     */
    public SimpleImageBanner setUnselectAnimClass(Class<? extends BaseAnimator> unselectAnimClass) {
        //this.mUnselectAnimClass = unselectAnimClass;
        return this;
    }

    /**
     * 设置数据集合
     *
     * @param list
     * @return 返回当前SimpleImageBanner
     */
    public SimpleImageBanner setDataList(List<BannerItem> list) {
        dataList = list;
        return this;
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        int action = touchEvent.getAction();
        if (action == PRIMARY_POINT_UP || action == CANCEL
            || action == NONE) {
            // 开始翻页
            startScroll();
        } else if (action == PRIMARY_POINT_DOWN) {
            // 停止翻页
            stopTurning();
        }
        return true;
    }

    /**
     * 异步操作
     *
     * @since 2021-04-30
     */
    class SwitchTask implements Runnable {
        private final WeakReference<SimpleImageBanner> reference;

        SwitchTask(SimpleImageBanner simpleImageBanner) {
            this.reference = new WeakReference<>(simpleImageBanner);
        }

        @Override
        public void run() {
            SimpleImageBanner simpleImageBanner = reference.get();
            if (simpleImageBanner != null) {
                if (simpleImageBanner.count > 1) {
                    int currentPage = bannerViewPager.getCurrentPage();
                    simpleImageBanner.currentItem = currentPage + 1;
                    simpleImageBanner.bannerViewPager.setCurrentPage(simpleImageBanner.currentItem, true);
                    simpleImageBanner.handler.postTask(this, period);
                }
            }
        }
    }

    /**
     * 监听item点击
     *
     * @param clickListener
     * @return SimpleImageBanner
     */
    public SimpleImageBanner setOnItemClickListener(OnItemClickListener clickListener) {
        this.onItemClickListener = clickListener;
        return this;
    }

    /**
     * 实现插值器
     *
     * @since 2021-04-30
     */
    private static class ReverseInterpolator implements Animator.TimelineCurve {
        @Override
        public float getCurvedTime(float value) {
            return Math.abs(1.0f - value);
        }
    }
}